package com.shuhe.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shuhe.JettyServer;
import com.shuhe.common.HttpClient;
import com.shuhe.domain.api.ApiResponseBody;
import com.shuhe.metastore.DBSql;
import com.shuhe.metastore.MetaMysql;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import static com.shuhe.common.CommonFunction.*;
import static com.shuhe.common.MyDateUtils.getNowDate;
import static com.shuhe.handler.CommonHandler.getFirstSelfDb;

public class ImportApiHandler extends HttpServlet {

    private static Logger logger = Logger.getLogger(ImportApiHandler.class);

    public static String db_type = JettyServer.globalProperties.getProperty("db.type");


    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp = setResponse(resp);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Connection metaConn = null;
        try {
            req.setCharacterEncoding("UTF-8");
            resp = setResponse(resp);
            String bodyStr = readAsChars(req);
            JSONObject bodyJson = JSONObject.parseObject(bodyStr);
            String operateType = bodyJson.getString("operateType");
            if (operateType == null) {
                //测试操作
                Map<String, String> heads = HttpClient.getAllHeaders(req);
                String sh_import_api_url = heads.get("sh_import_api_url");
                String respBody = HttpClient.postHttp(sh_import_api_url, bodyStr, heads);
                JSONObject jsonObject = new JSONObject();
                // 添加属性
                jsonObject.put("query_res", JSONObject.parseObject(respBody));
                //获取json对应的表、字段
                JSONObject tableObject = new JSONObject();
                tableObject.put("json_data", respBody);
                tableObject.put("db_type", db_type);
                String tableRes = HttpClient.postHttp("http://localhost:6888/get_json_table",
                        tableObject.toJSONString(), new HashMap<>());
                JSONObject tableJson = JSONObject.parseObject(tableRes);
                jsonObject.put("tables", tableJson.get("tables"));
                jsonObject.put("columns", tableJson.get("columns"));
                resp.getWriter().print(jsonObject);
            } else {
                if (operateType.equals("saveTableConfig")) {
                    //保存表配置
                    String api_id = bodyJson.getString("api_id");
                    String userName = bodyJson.getString("userName");
                    String dbType = bodyJson.getString("dbType");
                    JSONArray tableConfigs = bodyJson.getJSONArray("tableConfigs");
                    if (dbType.equals("meta")) {
                        metaConn = MetaMysql.connect();
                    } else {
                        metaConn = DBSql.connect();
                    }
                    ArrayList<String> sqls = new ArrayList<>();
                    sqls.add("delete from import_api_config_table where api_id = '" + api_id + "'");
                    String tableStr = "";
                    for (int i = 0; i < tableConfigs.size(); i++) {
                        JSONObject tableConfig = tableConfigs.getJSONObject(i);
                        String ori_table_name = tableConfig.getString("ori_table_name");
                        String new_table_name = tableConfig.getString("new_table_name").toLowerCase();
                        String primary_key = tableConfig.getString("primary_key");
                        if (primary_key == null){
                            primary_key = "";
                        }
                        sqls.add("insert into import_api_config_table(api_id, ori_table_name, new_table_name, " +
                                "primary_key, user_name, id) values('" + api_id + "', '" + ori_table_name + "', '" +
                                new_table_name + "', '" + primary_key + "', '" + userName +  "', '" + getUUID() + "')");
                        tableStr += ",'" + new_table_name + "'";
                    }
                    tableStr = tableStr.substring(1);
                    String sql = "select new_table_name from import_api_config_table where new_table_name in ("+
                            tableStr + ") and user_name <> '" + userName + "' " +
                            " union all\n" +
                            "select table_name from mxgc_user_table where table_name in (" + tableStr + ") and " +
                            "user_name <> '" + userName + "'";
                    ResultSet rs = MetaMysql.querySql(metaConn, sql);
                    if (rs.next()){
                        makeFailBody("输出表中文名称或英文名称重复", resp);
                    }
                    MetaMysql.batchExecSql(metaConn, sqls);
                    JSONObject respBody = new JSONObject();
                    JSONObject common = new JSONObject();
                    common.put("status", "200");
                    common.put("msg", "success");
                    respBody.put("common", common);
                    resp.getWriter().print(respBody);
                }
                if (operateType.equals("runImmediately")) {
                    //立即执行
                    String id = bodyJson.getString("id");
                    String userName = bodyJson.getString("userName");
                    String dbType = bodyJson.getString("dbType");
                    String respBody = runImmediately(id, userName, dbType);
                    resp.getWriter().print(JSONObject.parseObject(respBody));
                }
            }
        } catch (Exception e) {
            makeFailBody(e.getMessage(), resp);
            e.printStackTrace();
        } finally {
            closeDb(metaConn);
        }
    }

    //立即执行
    public String runImmediately(String id, String userName, String dbType) throws Exception {
        Connection metaConn = null;
        try {
            if (dbType.equals("meta")) {
                metaConn = MetaMysql.connect();
            } else {
                metaConn = DBSql.connect();
            }
            String sql = "select a.*, b.id as login_id, b.login_url, b.login_head, b.login_res, b.login_req, " +
                    "\n" +
                    " b.login_token_key, b.login_token_value, b.api_id " +
                    " from import_api_config a left join import_api_config_login b on a.id = b.api_id" +
                    " where a.id = '" + id + "'";
            ResultSet rs = DBSql.querySql(metaConn, sql);
            String respBody = "";
            if (rs.next()) {
                String loginUrl = rs.getString("login_url");
                String login_req = rs.getString("login_req");
                String login_head = rs.getString("login_head");
                Map<String, String> heads = new HashMap<>();
                JSONObject login_head_json = JSONObject.parseObject(login_head);
                if (login_head_json != null) {
                    for (String key : login_head_json.keySet()) {
                        heads.put(key, login_head_json.getString(key));
                    }
                }

                String login_token_value = "";
                if (loginUrl != null && loginUrl.length() > 0) {
                    //需要鉴权
                    respBody = HttpClient.postHttp(loginUrl, login_req, heads);
                    JSONObject body_json = JSONObject.parseObject(respBody);
                    String login_token_key = rs.getString("login_token_key");
                    login_token_value = body_json.getString(login_token_key);
                }
                //获取数据
                String dbStr = getFirstSelfDb(userName);
                sql = "select * from import_api_config_table where api_id = '" + id + "'";
                ResultSet rs1 = DBSql.querySql(metaConn, sql);
                ArrayList primary_keys = new ArrayList();
                ArrayList tables = new ArrayList();
                while (rs1.next()) {
                    String ori_table_name = rs1.getString("ori_table_name");
                    String new_table_name = rs1.getString("new_table_name");
                    if (new_table_name.indexOf(".") <= 0) {
                        new_table_name = dbStr + "." + new_table_name;
                    }
                    JSONObject tableJson = new JSONObject();
                    tableJson.put("ori_table_name", ori_table_name);
                    tableJson.put("new_table_name", new_table_name);
                    tables.add(tableJson);
                    String primary_key = rs1.getString("primary_key");
                    primary_keys.add(primary_key);
                }
                String start_time = getNowDate();
                respBody = getJsonData(rs, login_token_value);
                respBody = jsonToDb(respBody, primary_keys, tables);
                writeLog(rs, respBody, start_time);
            }
            return respBody;
        } finally {
            closeDb(metaConn);
        }

    }

    private String jsonToDb(String jsonData, ArrayList primary_keys, ArrayList tables) throws Exception {
        JSONObject body = new JSONObject();
        body.put("json_data", jsonData);
        body.put("db_type", db_type);
        body.put("primary_keys", primary_keys);
        body.put("tables", tables);
        String respBody = HttpClient.postHttp("http://localhost:6888/json_to_db", JSONObject.toJSONString(body),
                new HashMap<>());
        return respBody;
    }

    private String getJsonData(ResultSet rs, String login_token_value) throws Exception {
        String query_url = rs.getString("query_url");
        String query_head = rs.getString("query_head");
        String query_req = rs.getString("query_req");
        String query_token_key = rs.getString("query_token_key");
        if (query_token_key == null) {
            query_token_key = "";
        }
        if (login_token_value == null) {
            login_token_value = "";
        }
        Map<String, String> heads = new HashMap<>();
        JSONObject login_head_json = JSONObject.parseObject(query_head);
        for (String key : login_head_json.keySet()) {
            if (query_token_key.equals(key) && login_token_value.length() > 0) {
                heads.put(key, login_token_value);
            } else {
                heads.put(key, login_head_json.getString(key));
            }
        }
        String respBody = HttpClient.postHttp(query_url, query_req, heads);
        return respBody;
    }

    //写日志，包括开始时间，终止时间，请求，响应
    private void writeLog(ResultSet rs, String query_rep, String start_time) {
        Connection metaConn = null;
        try {
            metaConn = MetaMysql.connect();
            String query_url = rs.getString("query_url");
            String query_head = rs.getString("query_head");
            String query_req = rs.getString("query_req");
            String id = rs.getString("id");
            String log_sql = "insert into import_api_log(id, query_url, query_head, query_req, query_rep, start_time," +
                    " end_time, api_id) values('" + getUUID() + "','" + query_url + "','" + query_head + "','" +
                    query_req + "','" + query_rep + "','" + start_time + "','" + getNowDate() + "','" + id + "')";
            MetaMysql.execSql(metaConn, log_sql);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            closeDb(metaConn);
        }

    }

    private void makeFailBody(String msg, HttpServletResponse resp) {
        try {
            ApiResponseBody body = new ApiResponseBody();
            body.setStatus("201");
            body.setMsg(msg);
            resp.getWriter().write(JSONObject.toJSONString(body));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
